home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FM Towns: Free Software Collection 8
/
FM Towns Free Software Collection 8.iso
/
t_os
/
zousan
/
src
/
zousan.c
< prev
next >
Wrap
Text File
|
1994-06-01
|
13KB
|
570 lines
/*
* tiff16/256色 -> tiff32k色 変換プログラム 'ぞうさん'
* (C)1993,1994 By N.Takahashi
*
* ver0.61 1994/02/06 パレット無しのTiffデータに対応
* ver0.6 1994/02/05 新Tiff関数へ変更(圧縮形式に対応)
* ver0.5 1994/01/13 再度、変換ル-チンの高速化
* ver0.4 1994/01/05 ワイルドカード対応、バグ修正etc.
* ver0.3 1994/01/04 変換ル-チンの高速化
* ver0.2 1994/01/04 ファイル分割(zousan.c tiff.c graph.c)
* ver0.1 1993/11/11 初版
*/
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <ctype.h>
#include <dos.h>
#include <fcntl.h>
#include <EGB.h>
#include "tiff2.h" /* 拡張ライブラリIを買わないといけないかな(^^;) */
#include "graph.h"
/* Compile 方法 */
/* hcc zousan tiff2 graph -stack 200000 */
/* Prototype function */
void sum_ydata( int *ydt, int *sum, int *cnt );
void ren_file( void );
int exp_wild( char *path, char *file, char *dpath, char *dfile );
int isoldfile( char *fname );
void split_path( char *path, char *file, char *wd );
void sum_gdata256( int x, int y, int *cg, int *cr, int *cb );
void sum_gdata16( int x, int y, int *cg, int *cr, int *cb );
void title( void );
void usage( void );
int zousan( void );
void make_color( int *b, int *r, int *g, int b1, int r1, int g1, int hi );
int convert32k( void );
void adj_palette( char *pal, int col );
/* マクロ定義 */
#define CVCR(b,r,g) ((-(b)*816+(r)*5020-(g)*4203)/10000)
#define CVCB(b,r,g) (((b)*5020-(r)*1812-(g)*3214)/10000)
#define CVY(b,r,g) (((b)*1446+(r)*2955+(g)*5899)/10000)
#define CVY2(b,r,g) (((b)*1446+(r)*2955+(g)*5899))
#define CVB(cr,cb,y) ((y)*9719+(cr)*487+(cb)*17201)
#define CVR(cr,cb,y) ((y)*9707+(cr)*14021-(cb)*516)
#define CVG(cr,cb,y) ((y)*9707-(cr)*7142-(cb)*3957)
#define ATTR (_A_NORMAL|_A_RDONLY|_A_HIDDEN)
/* Global variable */
PALETTE16 *Pal16;
PALETTE256 *Pal256;
char *Gdata,*Gpal; /* 画像データ&パレット */
int SizX; /* 横サイズ */
int SizY; /* 縦サイズ */
int Gcol=0; /* 色数 */
char *Ddata; /* 変換した画像データ */
int Blur=0; /* Blur = 0 - 100 (Blur) */
int Tone=0; /* Tone = 0 - 100 (Tone of color) */
int BlurF=0,ToneF=0,DispF=0; /* オプション・フラグ */
int CompF=0;
int DirX[4]={0,1,0,-1};
int DirY[4]={-1,0,1,0};
void (*Sum_gdata)( int x, int y, int *cg, int *cr, int *cb );
char *Srcfile=NULL;
char *Dstfile=NULL;
#define PATH_MAX 128
#define FILE_MAX 16
char SPath[PATH_MAX]; /* ワイルドカード展開に使用 */
char SFile[FILE_MAX];
char DPath[PATH_MAX];
char DFile[FILE_MAX];
int WildF=0,DDirF=0; /* ワイルドカ-ドを使用できるようにしたら、
結構、制御が複雑になってしまった。 */
char Nowfile[128]; /* 現在、処理中のファイル名 */
/* 使用法 */
void usage( void ) {
printf( "usage: run386 zousan.exp [option] srcTiff16/256 [dstTiff]\n" );
printf( " -b<val> (Blur) ,val = 0 - 100\n" );
printf( " -t<val> (Tone of color) ,val = 0 - 100\n" );
printf( " -d (Display only)\n" );
printf( " -c (Compress Tiff file)\n\n" );
printf( " default: 16color = -b0 , -t20\n" );
printf( " 256color = -b0 , -t2\n" );
exit( 255 );
}
/* タイトル */
void title( void ) {
printf( "Tiff16/256色 -> Tiff32k色 変換プログラム 'ぞうさん'\n" );
printf( " (C)1993,1994 By N.Takahashi\n\n" );
}
/* メイン */
void main( int argc, char *argv[] ) {
int i;
title();
if( argc==1 )
usage();
for( i=1; i<argc; i++ ) { /* オプション展開 */
if( argv[i][0]=='-' || argv[i][0]=='/' )
switch( argv[i][1] ) { /* 手抜きしてる(^^;) */
case 'b':
case 'B':
Blur=atoi( argv[i]+2 );
BlurF=1;
break;
case 't':
case 'T':
Tone=atoi( argv[i]+2 );
ToneF=1;
break;
case 'd':
case 'D':
DispF=1;
break;
case 'c':
case 'C':
CompF=1;
break;
default:
usage();
break;
}
else {
if( Srcfile==NULL )
Srcfile=argv[i];
else
Dstfile=argv[i];
}
}
if( Srcfile==NULL )
usage();
isoldfile( NULL ); /* 基準時刻のセット */
/* 二度、変換しないようにするための準備 */
strcpy( SPath, Srcfile );
split_path( SPath, SFile, "*.TIF" );
if( strchr( SFile, '*' )!=NULL || strchr( SFile, '?' )!=NULL ) {
WildF=1;
}
if( Dstfile==NULL ) { /* 何も指定されていないとき */
strcpy( DPath, SPath );
*DFile='\0';
}
else { /* ファイルが指定されているとき */
strcpy( DPath, Dstfile );
split_path( DPath, DFile, "" );
if( WildF ) {
strcat( DPath, DFile );
strcat( DPath, "\\" );
*DFile='\0';
}
if( *DFile=='\0' ) /* ディレクトリのみのとき */
DDirF=1;
}
exp_wild( SPath, SFile, DPath, DFile );
}
/* ワイルドカ-ド展開 */
int exp_wild( char *path, char *file, char *dpath, char *dfile ) {
struct find_t fb;
int spl,dpl;
char *c;
spl=strlen( path );
dpl=strlen( dpath );
strcat( path, file );
if( _dos_findfirst( path, ATTR, &fb )==0 ) {
do {
path[spl]='\0';
dpath[dpl]='\0';
strcat( path, fb.name );
if( isoldfile( path ) ) {
/* 二度、変換しないようにするため */
sprintf( Nowfile, "%-12s : ", fb.name );
Srcfile=path;
Dstfile=dpath;
if( *dfile=='\0' ) { /* ファイルが指定されていないとき */
if( DDirF ) { /* ディレクトリのみのとき */
strcat( dpath, fb.name );
zousan();
}
else { /* 何も指定されていないとき */
strcat( dpath, fb.name );
if( ( c=strrchr( dpath, '.' ) )!=NULL ) {
*c='\0';
}
strcat( dpath, ".$$$" );
if( zousan()==0 )
ren_file();
}
}
else { /* ファイルが指定されているとき */
strcat( dpath, dfile );
zousan();
}
}
} while( _dos_findnext( &fb )==0 );
return( 0 );
}
else {
printf( "%-12s : ファイルが見つかりません。\n", _strupr(file) );
}
return( 1 );
}
/* タイムスタンプとシステムタイムとの比較 */
/* 使用前に基準時刻をセットしておくこと => isoldfile( NULL ) */
int isoldfile( char *fname ) {
static unsigned int sdate=0, stime=0;
struct dosdate_t sdt;
struct dostime_t stm;
unsigned int fdt,ftm;
int hd;
if( fname==NULL ) {
_dos_getdate( &sdt );
sdate=((sdt.year-1980)<<9)+(sdt.month<<5)+sdt.day;
_dos_gettime( &stm );
stime=(stm.hour<<11)+(stm.minute<<5)+(stm.second>>1);
}
else {
if( _dos_open( fname, _O_RDONLY, &hd )!=0 )
return( -1 );
_dos_getftime( hd, &fdt, &ftm );
_dos_close( hd );
if( fdt<sdate || (fdt==sdate && ftm<stime) )
return( 1 );
}
return( 0 );
}
/* ファイル名の交換 */
void ren_file( void ) {
char path[128],*c;
/* dst.$$$ を dst.TIF へ */
/* src.TIF を src.$IF へ */
strcpy( path, Srcfile );
if( ( c=strrchr( path, '.' ) )!=NULL ) {
*c='\0';
}
strcat( path, ".$IF" );
rename( Srcfile, path );
strcpy( path, Dstfile );
if( ( c=strrchr( path, '.' ) )!=NULL ) {
*c='\0';
}
strcat( path, ".TIF" );
rename( Dstfile, path );
}
/* PATH名とファイル名取り出し */
void split_path( char *path, char *file, char *wd ) {
char *c,*c2;
if( ( c=strrchr( path, ':' ) )==NULL ) {
c=path;
}
if( ( c2=strrchr( c, '\\' ) )==NULL ) {
c2=c;
}
if( *c2==':' || *c2=='\\' ) {
if( *(c2+1)!='\0' ) {
strcpy( file, c2+1 );
*(c2+1)='\0';
}
else
strcpy( file, wd );
}
else {
strcpy( file , path );
strcpy( path , "" );
}
/* '.' , '..' 対策 */
if( strcmp( file, "." )==0 || strcmp( file, ".." )==0 ) {
strcat( path, file );
strcat( path, "\\" );
strcpy( file, wd );
}
}
/* ぞうさんメイン */
int zousan( void ) {
Tiff *tp;
int rt;
tp=Tiff_new();
/* Tiff形式ロード */
rt=Tiff_load( Srcfile, tp );
if( rt!=Tiff__OK ) {
printf( "%s%s\n", Nowfile, Tiff_err[rt] );
return( 1 );
}
Tiff_decompress( tp ); /* 圧縮されている場合、展開する */
Tiff_make_palette( tp ); /* パレットがない場合に作成する */
Tiff_getgraph( &SizX, &SizY, &Gcol, &Gdata, &Gpal, tp );
/* 色数による設定 */
switch( Gcol ) {
case 256:
if( BlurF==0 ) /* デフォルト値 */
Blur=0;
if( ToneF==0 )
Tone=2;
Pal256=(PALETTE256 *)Gpal;
Sum_gdata=sum_gdata256;
break;
case 16:
if( BlurF==0 )
Blur=0;
if( ToneF==0 )
Tone=20;
Pal16=(PALETTE16 *)Gpal;
Sum_gdata=sum_gdata16;
break;
default:
printf( "%s扱えないデータ形式です。\n", Nowfile );
return( 1 );
}
if( Blur<0 )
Blur=0;
if( Blur>100 )
Blur=100;
if( Tone<0 )
Tone=0;
if( Tone>100 )
Tone=100;
adj_palette( Gpal, Gcol ); /* パレットデータの調整 */
/* Tiff_load直後のパレットデータは、
そのままでは使いにくい */
if( (Ddata=(char *)malloc( SizX*SizY/2 ))==NULL ) {
printf( "メモリが足りません。\n" );
Tiff_delete( tp );
return( 1 );
}
/* 32K色変換 */
if( convert32k() ) {
printf( "強制中断します。%*c\n", 60, 0x20 );
G_dosterm();
exit( 1 );
}
/* ディスプレイ表示 */
if( DispF ) {
G_screen( 10, 0 ); /* 320*240 3万色 */
G_screen( 10, 1 );
G_enlarge( 2, 2, 0, 0, 320, 240 );
G_active( 1, 3, 1 );
G_put( 0,0, SizX/2-1,SizY/2-1, Ddata );
_getch(); /* 何かキー入力が有るまで待つ */
G_dosterm(); /* DOS画面に戻す */
Tiff_delete( tp );
free( Ddata );
return( 1 );
}
/* Tiff形式セーブ */
if( Dstfile!=NULL && !DispF ) {
Tiff_delete( tp );
tp=Tiff_new();
Tiff_setgraph( tp, SizX/2, SizY/2, 32768, Ddata, NULL );
if( CompF )
Tiff_compress( tp ); /* -c 指定時にデータを圧縮する */
rt=Tiff_save( Dstfile, tp );
if( rt!=0 ) {
printf( "%s%s\n", Nowfile, Tiff_err[rt] );
Tiff_delete( tp );
return( 1 );
}
}
Tiff_delete( tp );
return( 0 );
}
/* 3万色変換 */
int convert32k( void ) {
int x,y,a,b,hi,bc,bcc;
int cc,cg,cr,cb;
int yc,yg,yr,yb;
int g0,r0,b0;
int xx,yy,xd,yd;
int ydt[16];
for( y=0; y<SizY-1; y+=2 ) {
if( (y&31)==0 ) {
printf( "%s変換中です。(%d%)\r", Nowfile, y*100/SizY );
}
if( _kbhit() ) {
if( _getch()==0x1b )
return( 1 );
}
yd=(y/2*SizX)/2;
for( x=0; x<SizX-1; x+=2 ) {
xd=x/2;
cg=cr=cb=cc=yg=yr=yb=yc=0; /* 色と輝度の積算 4×4 */
for( a=-1; a<=2; a++ ) {
xx=x+a;
for( b=-1; b<=2; b++ ) {
yy=y+b;
if( xx>=0 && xx<SizX && yy>=0 && yy<SizY ) {
Sum_gdata( xx, yy, &g0, &r0, &b0 );
ydt[a+1+(b+1)*4]=CVY2( b0, r0, g0 );
cg+=g0;
cr+=r0;
cb+=b0;
cc++;
if( a>=0 && a<=1 && b>=0 && b<=1 ) {
yg+=g0;
yr+=r0;
yb+=b0;
yc++;
}
}
else
ydt[a+1+(b+1)*4]=-1;
}
}
sum_ydata( ydt, &bc, &bcc );
hi=( bcc>0 )?(bc/bcc)/10000 : 0;
cr/=cc;
cg/=cc;
cb/=cc;
yr/=yc;
yg/=yc;
yb/=yc;
make_color( &cb, &cr, &cg, yb, yr, yg, hi );
/* 色データ書き込み */
*((unsigned short *)Ddata+xd+yd)=G_color32k(cg, cr, cb);
}
}
printf( "%s変換終了しました。(100%)\n", Nowfile );
return( 0 );
}
/* 色作成 */
void make_color( int *bb, int *rr, int *gg, int bb1, int rr1, int gg1, int hi ) {
int y,cr,cb,y0,b;
cr=CVCR( *bb, *rr, *gg ); /* YC分離 */
cb=CVCB( *bb, *rr, *gg );
y=CVY( bb1, rr1, gg1 );
y0=CVY( *bb, *rr, *gg );
b=abs(*rr-rr1)+abs(*bb-bb1)+abs(*gg-gg1);
b=1000/(b+1);
b+=Blur;
if( b>100 )
b=100;
y+=(y0-y)*b/100; /* にじみ具合の調整 */
y+=hi*Tone/100; /* 色調の調整 */
*bb=CVB( cr, cb, y ); /* RGB色合成 */
*bb=( *bb>=0 )?(*bb+5000)/10000 : 0;
*rr=CVR( cr, cb, y );
*rr=( *rr>=0 )?(*rr+5000)/10000 : 0;
*gg=CVG( cr, cb, y );
*gg=( *gg>=0 )?(*gg+5000)/10000 : 0;
if( *bb>255 )
*bb=255;
if( *rr>255 )
*rr=255;
if( *gg>255 )
*gg=255;
}
/* パレット調整 */
void adj_palette( char *pal, int col ) {
int i;
/* Tiffのパレットデータの調整 */
for( i=0; i<col*3; i++ ) {
*((unsigned short *)pal+i)=*((unsigned short *)pal+i)>>8;
}
}
/* 16色データ取得 */
void sum_gdata16( int x, int y, int *cg, int *cr, int *cb ) {
int cc;
cc=Gdata[(x+y*SizX)/2];
if( x&1 )
cc=cc>>4;
else
cc=cc&15;
*cb=Pal16->blue[cc]; /* パレットによる色変換 */
*cr=Pal16->red[cc];
*cg=Pal16->green[cc];
}
/* 256色データ取得 */
void sum_gdata256( int x, int y, int *cg, int *cr, int *cb ) {
int cc;
cc=Gdata[x+y*SizX];
*cb=Pal256->blue[cc]; /* パレットによる色変換 */
*cr=Pal256->red[cc];
*cg=Pal256->green[cc];
}
/* 輝度差データ取得 */
void sum_ydata( int *ydt, int *sum, int *cnt ) {
int i,a,b,k,yc;
*sum=*cnt=0;
for( a=1; a<=2; a++ ) {
for( b=1; b<=2; b++ ) {
yc=ydt[a+b*4]; /* 対象点の輝度 */
for( i=0; i<4; i++ ) {
k=ydt[a+DirX[i]+(b+DirY[i])*4]; /* 隣接点の輝度 */
if( k>=0 ) {
k=yc-k;
if( k>=0 ) { /* 対象点の方が輝度が高い時 */
*sum+=k;
(*cnt)++;
}
}
}
}
}
}